/*
 * @Descripttion: Lutongli代码
 * @version: 1.0.0
 * @Author: LutongLi
 * @Date: 2025-06-02 15:28:27
 * @LastEditTime: 2025-06-05 00:57:46
 */
package cmd

import (
	"errors"
	"fmt"

	"github.com/gin-gonic/gin"
	"github.com/infraboard/mcube/logger/zap"
	"github.com/spf13/cobra"

	"gitee.com/king_max/restful-api-demo/apps"
	// hosthttpapi "gitee.com/king_max/restful-api-demo/apps/host/http"
	_ "gitee.com/king_max/restful-api-demo/apps/all"
	"gitee.com/king_max/restful-api-demo/conf"
)

//程序的逻辑组装
// 启动程序时的命令： demo start
// 服务启动流程大致如下:
// 	1.读取配置,初始化全局变量
// 	2.初始化全局日志配置,加载全局日志实例
//  3.初始化服务层,将我们的服务实例注册到1oc
//  4.创建服务,监听中断信号
//  5.启动服务


var  (
	//pusher service config option
	confType string
	confFile string
	confETCD string
)


var StartCmd = &cobra.Command{
	Use: "start",
	Short: "启动 demo 后端API",
	Long:  "启动 demo 后段API",
	RunE: func(cmd *cobra.Command,args []string) error {
		//加载程序配置
		err := conf.LoadConfigFromToml(confFile)
		if err != nil{
			// panic(err)
			return err
		}

		//初始化全局日志logger
		if err := loadGlobalLogger();err !=nil{
			return err
		}
		//加载Host service的实体类
		// service := impl.NewHostServiceImpl()
		
		//将注册Hostservice的实例注册到IOC
		// apps.HostService = impl.NewHostServiceImpl()
		//我们采用 _ import "gitee.com/king_max/restful-api-demo/apps/host/impl"
		apps.InitImpl()

		//通过Host API Handler提供HTTP Restful接口
		// api := hosthttpapi.NewHostHTTPHandler()
		//从IOC中获取依赖
		// api.Config()
		//提供一个Gin Router
		g := gin.Default()
		// api.Regsitry(g)
		apps.InitGin(g)
		return g.Run(conf.C().App.HttpAddr())
		return errors.New("no flags find")
	},
}

// 还没有初始化Logger实例


func init(){
	StartCmd.PersistentFlags().StringVarP(&confFile,"config","f","etc/demo.toml","demo api 配置文件路径")
	RootCmd.AddCommand(StartCmd)
}


//思考问题
// 1.http Api、Grpc API 需要启动，消息总线也需要监听，比如负责注册配置，这些模块都是独立的
// 需要在程序启动时，进行启动，如果都写在start函数里面，就会显得异常复杂，且不易维护

// 2.服务的优雅关闭怎么办？
//  像K8s这些服务，外部都会发送一个terminal(中断信号)给你的程序，程序是需要处理这个信号
//  需要实现程序优雅关闭逻辑的处理： 由先后顺序，
//	 1. api 层的关闭（http,Grpc,）
//   2. 消息总线
//	 3. 关闭数据库连接
//   4. 如果 使用注册中心，最后才是完成下线
//   5. 退出完毕


//初始化logger实例,日志实例全局只有一个
func loadGlobalLogger() error {
	var (
		logInitMsg string
		level 	   zap.Level
	)
	lc := conf.C().Log
	lv,err :=zap.NewLevel(lc.Level)
	if err != nil{
		logInitMsg = fmt.Sprintf("%s,use default level INFO",err)
		level = zap.InfoLevel
	} else{
		level = lv
		logInitMsg = fmt.Sprintf("log level: %s",lv)
	}
	//使用默认配置初始化Looger的全局配置
	zapConfig := zap.DefaultConfig()
	
	//配置日志的level级别，
	zapConfig.Level = level
	
	//是否每次启动，都论断一次日志
	zapConfig.Files.RotateOnStartup = false

	//配置日志打印输出方式
	switch lc.To{
	case conf.ToStdout:
		//把日志打印到标准输出
		zapConfig.ToStderr = true
		//不把日志输出到文件中
		zapConfig.ToFiles = false
	case conf.ToFile:
		zapConfig.Files.Name="api.log"
		zapConfig.Files.Path = lc.PathDir
	}

	//配置日志输出的格式
	switch lc.Format {
	case conf.JSONFormat:
		zapConfig.JSON = true
	}

	//把配置 应用到全局logger
	if err := zap.Configure(zapConfig);err != nil{
		return err
	}
	zap.L().Named("INIT").Info(logInitMsg)
	return nil
}
